// <template>
//   <div class=" odn-table el-table" :class="tableClass" ref="tableRef">
//     <div class="el-table__header-wrapper" ref="headerRef" :scrollLeft.prop="scrollLeft">
//       <table cellspacing="0" cellpadding="0" border="0" class="el-table__header">
//         <thead class="has-gutter">
//           <tr>
//             <th v-for="(col, colIndex) in fields" :key="col.field">
//               <div class="cell" :style="`width:${col.width}px;`" v-odnStretch="{
//                   positions: ['right'],
//                   width: '10px',
//                   isOutRange: true,
//                   onResize: (dom) => {
//                     thWidthChange(dom, col);
//                   },
//                 }" @click="tableEventFn('header', { col, colIndex }, $event)" @contextmenu.prevent="tableEventFn('header', { col, colIndex }, $event)">
//                 <!-- 插槽 data是slot-scope对象可获取到的属性-->
//                 <slot name="headerCell" :data="{ col, colIndex }">
//                   <span>{{ col.title }}</span>
//                   <span v-if="col.field == sortField" class="sort" :class="[sortDirection]"></span>
//                   <span class="filterBtn" @click.stop="tableEventFn('header-filter', { col, colIndex }, $event)">
//                     <i class="sf-tree-filter fl-icon" :class="{ isFilter: filterFields.includes(col.field) }"></i>
//                   </span>
//                   <span v-if="col.editable && editable" class="filterBtn batch-update" @click.stop="tableEventFn('header-update', { col, colIndex }, $event)">
//                     <i class="sf-check-batchupdate fl-icon"></i>
//                   </span>
//                 </slot>
//               </div>
//             </th>
//             <th class="gutter" style="width: 8px;">
//               <div style="width: 8px;"></div>
//             </th>
//           </tr>
//         </thead>
//       </table>
//     </div>
//     <div class="el-table__body-wrapper" ref="bodyRef" @scroll.passive="bodyScroll($event)">
//       <!-- 撑起虚拟高度   -->
//       <div :style="`height:${totalHeight}px;width:${totalWith}px;`"></div>
//       <div class="el_table_view" :style="`top:${tableTop}px`">
//         <table cellspacing="0" cellpadding="0" border="0" class="el-table__body">
//           <tbody>
//             <tr class="el-table_row" v-for="(row, rowIndex) in displayData" :key="row[datakey]" :class="getRowclass(row)" @click="tableEventFn('row', { row, rowIndex }, $event)"
//               @contextmenu.prevent="tableEventFn('row', { row, rowIndex }, $event)" @dblclick="tableEventFn('row', { row, rowIndex }, $event)">
//               <td colspan="1" rowspan="1" v-for="(col, colIndex) in fields" :key="col.field">
//                 <div class="cell el-tooltip" :style="`width:${col.width}px;`" v-odnTips @click="tableEventFn('cell', { col, colIndex, row, rowIndex }, $event)"
//                   @contextmenu="tableEventFn('cell', { col, colIndex, row, rowIndex }, $event)" @dblclick="tableEventFn('cell', { col, colIndex, row, rowIndex }, $event)">
//                   <!-- 默认的编辑状态和非编辑状态 -->
//                   <template v-if="editable && col.editable && currEditCell.row == row && currEditCell.col == col">
//                     <div class="input_wrap">
//                       <el-input-number v-if="col.type == 'Integer' || col.type == 'Long'" v-model="row[col.field]" :size="`mini`" :precision="0" v-odnFocus :controls="false"
//                         @keyup.enter.native="enterInEditcell($event)" @blur="editedCell({ col, colIndex, row, rowIndex })">
//                       </el-input-number>
//                       <el-input-number v-if="col.type == 'Double'" v-model="row[col.field]" :controls="false" :size="`mini`" v-odnFocus @keyup.enter.native="enterInEditcell($event)"
//                         @blur="editedCell({ col, colIndex, row, rowIndex })"></el-input-number>
//                       <el-input v-if="col.type == 'String'" v-model="row[col.field]" v-odnFocus :size="`mini`" @keyup.enter.native="enterInEditcell($event)"
//                         @blur="editedCell({ col, colIndex, row, rowIndex })"></el-input>
//                     </div>
//                   </template>
//                   <template v-else>
//                     <slot name="bodyCell" :data="{ col, colIndex, row, rowIndex }">
//                       <span v-if="col.formatter">
//                         <pre>{{ col.formatter(row[col.field], row, col) }}</pre>
//                       </span>
//                       <span v-else>
//                         <pre>{{ row[col.field] }}</pre>
//                       </span>
//                     </slot>
//                   </template>
//                 </div>
//               </td>
//             </tr>
//             <!-- 虚拟行高，加载后移除 -->
//             <tr class="el-table_row" id="tr_when_virtual" v-if="virtual && showTestTr" style="visibility: hidden;">
//               <td>
//                 <div class="cell el-tooltip">1</div>
//               </td>
//             </tr>
//           </tbody>
//         </table>
//       </div>
//     </div>
//   </div>
// </template>

// <script>
// import { ref, watch, computed, reactive, toRefs, onMounted, onUnmounted } from "@vue/composition-api";

// export default {
//   props: {
//     data: {
//       // 指定数据体，必传
//       type: Array,
//       required: true,
//     }, // 表数据
//     datakey: {
//       // 指定表的key列， 必传.   不赋默认值是防止使用者忽略该项
//       type: String,
//       required: true,
//       // default() { return "id" }
//     }, // key 列
//     fields: {
//       // 表字段 [{field:"",type:"",title,width,sortable,formatter,editable......}]  type取值为业务中的类型.   可编辑类型以后有待增加  下拉，日期等情况
//       type: Array,
//       required: true,
//     },
//     size: {
//       type: String,
//       default() {
//         return "mini";
//       }, //medium / small / mini
//     },
//     border: {
//       type: Boolean,
//       default() {
//         return true;
//       },
//     },
//     editable: {
//       type: Boolean,
//       default() {
//         return false;
//       },
//     },
//     rowClassName: {
//       // 表格行的class
//       type: Function,
//       default: function (row) {
//         return "class-on-row";
//       },
//     },
//     virtual: {
//       type: Boolean,
//       default() {
//         return false;
//       },
//     },
//     // 下面两个属性支持sync
//     sortField: {
//       type: String,
//       default() {
//         return "";
//       },
//     },
//     sortDirection: {
//       type: String,
//       default() {
//         return "";
//       },
//     },
//     filterFields: {
//       type: Array,
//       default() {
//         return [];
//       },
//     },
//     isScrollToLeft: {
//       // 滚动条是否滚动到最左侧
//       type: Boolean,
//       default() {
//         return false;
//       },
//     },
//     isScrollToTop: {
//       // 滚动条是否滚动到最顶端
//       type: Boolean,
//       default() {
//         return false;
//       },
//     },
//   },
//   setup(props, ctx) {
//     let state = reactive({
//       guid: "t_" + ~~(Math.random() * 1000), //一个随机id,
//       scrollLeft: 0, // 表头和表身的wrap的滚动位置
//       scrollTop: 0, // 滚动条位置
//       tableHeight: 0,
//       rowHeight: 24,
//       showTestTr: true, // 显示测试的tr,
//       currEditCell: {}, // 当前编辑的单元格，{row,col}。 它不能直接在data 上添加属性。会触发watch props.data
//     });
//     let computeds = {
//       tableClass: computed(() => {
//         return {
//           ["el-table--" + props.size]: true,
//           "el-table--border": props.border,
//           "table-virtual": props.virtual,
//         };
//       }),
//       displayData: computed(() => {
//         if (props.virtual) {
//           if (state.tableHeight && state.rowHeight) {
//             let startIndex = Math.floor(state.scrollTop / state.rowHeight);
//             let limit = Math.ceil(state.tableHeight / state.rowHeight);
//             return props.data.slice(startIndex, startIndex + limit);
//           }
//         } else {
//           return props.data;
//         }
//       }),
//       totalWith: computed(() => {
//         let width = 0;
//         props.fields.forEach((col) => {
//           width += col.width + 1;
//         });
//         return width;
//       }),
//       totalHeight: computed(() => {
//         return props.data.length * state.rowHeight || 1;
//       }),
//       tableTop: computed(() => {
//         return ~~(state.scrollTop / state.rowHeight) * state.rowHeight - 1; // tableTop不能是scrollTop,必须是通过startIndex计算出来的值。
//       }),
//     };
//     // 监听数据， 滚动条归位. 之后才compute displayData
//     watch(
//       () => props.data,
//       () => {
//         if (state.scrollLeft || state.scrollTop) {
//           props.isScrollToLeft && (state.scrollLeft = 0);
//           props.isScrollToTop && (state.scrollTop = 0);
//           ctx.refs.bodyRef.scrollTo({ top: state.scrollTop, left: state.scrollLeft, behavior: "auto" });
//         }
//       },
//       {
//         flush: "post",
//       }
//     );
//     let methods = {
//       getRowclass(row) {
//         let name = props.rowClassName(row);
//         return { [name]: true };
//       },
//       //四个属性 info:{row,col,rowIndex,colIndex}
//       tableEventFn(from, info, $event) {
//         let eventType = $event.type;
//         ctx.emit(`${from}-${eventType}`, info, $event);
//         // 如果点击单元格，且在编辑状态，则把data.field__edit=true
//         if (from == "cell" && eventType == "click" && props.editable && info.col.editable) {
//           if (!(info.row == state.currEditCell.row && info.col == state.currEditCell.col)) {
//             state.currEditCell = info;
//             state.currEditCell.oldValue = info.row[info.col.field];
//             ctx.emit("cell-editing", state.currEditCell);
//           }
//         }
//         //排序
//         if (from == "header" && eventType == "click" && info.col.sortable) {
//           // 如果点击了拖拽区域，则不进行查询
//           if ($event && /^area[0-9]+$/g.test($event.path[0].id)) {
//             return;
//           }
//           let dir = "",
//             field = info.col.field;
//           if (field == props.sortField) {
//             props.sortDirection == "desc" && (dir = "asc");
//             props.sortDirection == "asc" && (dir = "desc");
//             props.sortDirection == "" && (dir = "asc");
//           } else {
//             dir = "asc";
//           }
//           ctx.emit("update:sortDirection", dir);
//           ctx.emit("update:sortField", dir ? field : "");
//           // 通过前面两个事件， 下面这个事件大部分时候都不用监听了
//           ctx.emit("sort-change", { col: info.col, direction: dir });
//         }
//       },
//       editedCell(info) {
//         let newValue = info.row[info.col.field];
//         if (newValue == undefined) {
//           newValue = info.row[info.col.field] = state.currEditCell.oldValue == null ? null : 0;
//         }
//         ctx.emit("cell-edited", { ...state.currEditCell, newValue });
//         state.currEditCell = {};
//       },
//       enterInEditcell($event) {
//         $event.target.blur();
//       },
//       thWidthChange(dom, col) {
//         ctx.emit("col-width-change", col, parseFloat(dom.style.width));
//       },
//       bodyScroll($event) {
//         state.scrollLeft = $event.target.scrollLeft;
//         state.scrollTop = $event.target.scrollTop;
//         ctx.emit("body-scroll", $event);
//       },
//     };
//     onMounted(() => {
//       //插入虚拟行，计算行高
//       if (props.virtual) {
//         let tr = ctx.refs.bodyRef.querySelector("#tr_when_virtual");
//         let rect = tr.getClientRects();
//         if (rect.length) {
//           state.rowHeight = tr.getClientRects()[0].height;
//         }
//         // tr.remove();  直接remove，vue会报异常
//         state.showTestTr = false;
//       }
//       // 获取table的初始高度
//       const resizeObserver = new ResizeObserver((entries) => {
//         state.tableHeight = entries[0].contentRect.height;
//       });
//       resizeObserver.observe(ctx.refs.bodyRef);
//     });
//     return {
//       ...toRefs(state),
//       ...computeds,
//       ...methods,
//     };
//   },
// };
// </script>

// <style lang="less" scoped>
// .odn-table {
//   flex: 1;
//   display: flex;
//   height: 100%;
//   flex-direction: column;
//   border: 1px solid rgb(213, 213, 213);
//   &.el-table--border th,
//   &.el-table--border td {
//     border-right: 1px solid #ebeef5;
//     border-bottom: 1px solid #ebeef5;
//   }
//   .el-table__header-wrapper {
//     th {
//       box-sizing: border-box;
//       padding: 3px 0;
//       font-weight: 500;
//       font-size: 100%;
//       color: #000;
//       background: #f5fbff;
//       border: none;
//       border-right: 1px solid #ebeef5;
//       border-bottom: 1px solid #ebeef5;
//     }
//   }
//   .el-table__body-wrapper {
//     td {
//       box-sizing: border-box;
//       padding: 0;
//     }
//     tr:hover {
//       background-color: #f5f7fa;
//     }
//   }
//   .el-table__body-wrapper {
//     flex: 1;
//     overflow: auto;
//   }
//   .el_table_view {
//     position: absolute;
//     top: 0;
//     overflow: hidden;
//   }
//   .cell {
//     font-size: 0.12rem;
//     overflow-x: hidden;
//     padding-right: 10px;
//     line-height: 24px;
//     height: 24px;
//     min-width: 50px;
//     &:hover {
//       .batch-update {
//         display: block;
//       }
//     }
//   }
//   &.table-virtual {
//     .cell {
//       white-space: nowrap; // 虚拟时，不换行，统一行高
//     }
//   }
//   // .input_wrap {
//   // position: absolute; // 编辑框浮出来
//   // top: 0;
//   // left: 0;
//   // right: 0;
//   // bottom: 0;
//   // }
//   .filterBtn {
//     float: right;
//     cursor: pointer;
//     .fl-icon {
//       font-size: 0.12rem;
//       color: #000;
//       &:hover {
//         color: #409eff;
//       }
//     }
//     .isFilter {
//       color: #409eff;
//     }
//     &.batch-update {
//       display: none;
//       margin-right: 3px;
//     }
//   }
//   .sort {
//     display: inline-block;
//     width: 0.1rem;
//     height: 0.1rem;
//     margin-left: 0.1rem;
//     &.asc::after {
//       content: "▲";
//     }
//     &.desc::after {
//       content: "▼";
//     }
//   }
// }
// </style>
